home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Languguage OS 2
/
Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO
/
language
/
ici
/
ici.cpi
/
array.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-10-27
|
5KB
|
286 lines
#include "ptr.h"
#include "exec.h"
#include "op.h"
#include "int.h"
#include "buf.h"
int
growarray(a, n)
register array_t *a;
register int n;
{
register object_t **e;
if (objof(a)->o_flags & O_ATOM)
{
error = "attempt to write on constant array";
return 1;
}
if (a->a_base == NULL)
{
/*
* Virgin array, first memory allocation (only happens because
* of special case in ici_evaluate).
*/
n += 4;
n *= sizeof(object_t *);
if ((e = (object_t **)zalloc(n)) == NULL)
return 1;
a->a_base = e;
a->a_top = e;
a->a_limit = e + n / sizeof(object_t *);
}
else
{
/*
* Append space to the array. We don't use realloc to ensure
* that memory exhaustion is cleanly recovereable.
*/
if ((a->a_limit - a->a_base) * 3 / 2 < a->a_limit - a->a_base + n)
n += (a->a_limit - a->a_base) + 10;
else
n = (a->a_limit - a->a_base) * 3 / 2;
n *= sizeof(object_t *);
if ((e = (object_t **)zalloc(n)) == NULL)
return 1;
memcpy((char *)e, (char *)a->a_base,
(a->a_limit - a->a_base) * sizeof(object_t *));
a->a_top = e + (a->a_top - a->a_base);
zfree((char *)a->a_base);
a->a_base = e;
a->a_limit = e + n / sizeof(object_t *);
}
return 0;
}
int
faultarray(a, i)
register array_t *a;
register int i;
{
if (objof(a)->o_flags & O_ATOM)
{
error = "attempt to write on constant array";
return 1;
}
if (i < 0)
{
sprintf(buf, "attempt to write at array index %d\n", i);
error = buf;
return 1;
}
++i;
i -= a->a_top - a->a_base;
if (pushcheck(a, i))
return 1;
while (--i >= 0)
*a->a_top++ = objof(&o_null);
return 0;
}
int
badindex()
{
error = "array index range error";
return 1;
}
/*
* Return a new array. It will have room for at least 6 elements from
* the start.
*/
array_t *
new_array()
{
register array_t *a;
if ((a = talloc(array_t)) == NULL)
return NULL;
objof(a)->o_type = &array_type;
objof(a)->o_tcode = TC_ARRAY;
objof(a)->o_flags = 0;
objof(a)->o_nrefs = 1;
rego(a);
a->a_base = NULL;
a->a_top = NULL;
a->a_limit = NULL;
/*
* Note that the following FEW_OBJS is choosen to correspond with the
* size of the smaller special memory list.
*/
if ((a->a_base = (object_t **)zalloc(FEW_OBJS*sizeof(object_t *))) == NULL)
return NULL;
a->a_top = a->a_base;
a->a_limit = a->a_base + FEW_OBJS;
return a;
}
STATIC long
mark_array(a)
register array_t *a;
{
register object_t **e;
long mem;
objof(a)->o_flags |= O_MARK;
mem = sizeof(array_t) + (a->a_limit - a->a_base) * sizeof(object_t *);
for (e = a->a_base; e < a->a_top; ++e)
mem += mark(*e);
return mem;
}
void
free_array(a)
register array_t *a;
{
if (a->a_base != NULL)
zfree((char *)a->a_base);
/*
* This special guard is only needed for arrays because the execution
* loop uses static arrays which get their memory freed by this
* routine, but don't have allocated bodies.
*/
if (objof(a)->o_nrefs == 0)
zfree((char *)a);
}
STATIC int
cmp_array(a1, a2)
array_t *a1;
array_t *a2;
{
register int i;
if (a1 == a2)
return 0;
if ((i = a1->a_top - a1->a_base) != a2->a_top - a2->a_base)
return 1;
return memcmp((char *)a1->a_base, (char *)a2->a_base,
i * sizeof(object_t *));
}
STATIC object_t *
copy_array(a)
register array_t *a;
{
register array_t *na;
register int n;
if ((na = new_array()) == NULL)
return NULL;
if (pushcheck(na, (n = a->a_top - a->a_base)))
goto fail;
memcpy((char *)na->a_base, (char *)a->a_base, n * sizeof(object_t *));
na->a_top += n;
return objof(na);
fail:
loose(na);
return NULL;
}
STATIC long
hash_array(a)
register array_t *a;
{
register int i;
long h;
h = i = a->a_top - a->a_base;
while (--i >= 0)
h += (long)a->a_base[i];
return h;
}
STATIC int
assign_array(a, k, v)
register array_t *a;
object_t *k;
object_t *v;
{
register int i;
if (!isint(k))
return assign_simple(objof(a), k, v);
i = intof(k)->i_value;
if (arrayprobe(a, i))
return 1;
a->a_base[i] = v;
return 0;
}
STATIC object_t *
fetch_array(a, k)
register array_t *a;
object_t *k;
{
register int i;
if (!isint(k))
return fetch_simple(objof(a), k);
if ((i = intof(k)->i_value) >= 0 && i < a->a_top - a->a_base)
return a->a_base[i];
return objof(&o_null);
}
/*
* mark any any... => array (os)
*/
STATIC int
op_offsq()
{
register array_t *a;
register int i;
for (i = 1; os->a_top - i > os->a_base; ++i)
{
if (o_top[-i] == objof(&o_mark))
break;
}
if (o_top[-i] != objof(&o_mark))
return badindex();
--i;
if ((a = new_array()) == NULL || pushcheck(a, i))
return 1;
memcpy((char *)a->a_base, (char *)&o_top[-i], i * sizeof(object_t *));
a->a_top += i;
o_top -= i;
o_top[-1] = objof(a);
loose(a);
--x_top;
return 0;
}
/*
* obj => array 0 (the array contains the obj)
*/
STATIC int
op_mklvalue()
{
array_t *a;
if ((a = new_array()) == NULL)
return 1;
*a->a_top++ = o_top[-1];
o_top[-1] = objof(a);
*o_top++ = objof(o_zero);
loose(a);
--x_top;
return 0;
}
type_t array_type =
{
mark_array,
free_array,
hash_array,
cmp_array,
copy_array,
assign_array,
fetch_array,
"array"
};
op_t o_offsq = {OBJ(TC_OP, op_type), op_offsq};
op_t o_mklvalue = {OBJ(TC_OP, op_type), op_mklvalue};